#!/bin/bash
###############################################################################
#       脚本名称: toml.sh
#       功能描述: TOML配置文件操作模块
#       作者: 林再来
#       日期: 2025-10-14
#       版本: 1.0
#       功能:
#           1、TOML文件读取、写入、删除操作
#           2、TOML格式验证
#           3、TOML文件合并
#           4、哈希计算和变更检测
#       依赖:
#           1、toml-cli (可选，优先使用)
#           2、python3 + toml模块 (备选)
#           3、纯Shell实现 (最后备选，功能受限)
###############################################################################

# 注意：不使用严格模式，避免影响交互式 shell

# TOML工具命令路径
TOML_CMD=""
TOML_METHOD=""  # cli|python|shell

###############################################################################
# 初始化和工具检测
###############################################################################

# 函数: 初始化TOML处理器
_toml_init() {
    # 方法1: 检查toml命令行工具
    if command -v toml &>/dev/null; then
        TOML_CMD="toml"
        TOML_METHOD="cli"
        return 0
    fi
    
    # 方法2: 检查Python + toml模块
    if command -v python3 &>/dev/null; then
        if python3 -c "import toml" 2>/dev/null; then
            TOML_CMD="python3"
            TOML_METHOD="python"
            return 0
        fi
    fi
    
    # 方法3: 使用纯Shell实现（功能受限）
    TOML_METHOD="shell"
    log_warn "toml" "未找到toml工具，使用纯Shell实现（功能受限）"
    return 0
}

###############################################################################
# 核心功能 - Python实现
###############################################################################

# 函数: Python读取TOML值
_toml_read_python() {
    local file="$1"
    local path="$2"
    local default="${3:-}"
    
    python3 << EOF
import toml
import sys

try:
    data = toml.load("$file")
    keys = "$path".strip('.').split('.')
    value = data
    for key in keys:
        if key:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                print("$default")
                sys.exit(0)
    print(value if value is not None else "$default")
except Exception as e:
    print("$default")
    sys.exit(1)
EOF
}

# 函数: Python写入TOML值
_toml_write_python() {
    local file="$1"
    local path="$2"
    local value="$3"
    local type="${4:-string}"
    
    # 创建备份
    [[ -f "$file" ]] && cp "$file" "${file}.bak"
    
    python3 << EOF
import toml
import sys
import os

try:
    # 读取现有数据
    data = {}
    if os.path.exists("$file") and os.path.getsize("$file") > 0:
        with open("$file", 'r') as f:
            data = toml.load(f)
    
    # 解析路径
    keys = "$path".strip('.').split('.')
    
    # 设置值
    current = data
    for i, key in enumerate(keys[:-1]):
        if key:
            if key not in current:
                current[key] = {}
            current = current[key]
    
    # 转换值类型
    final_value = "$value"
    if "$type" == "number":
        try:
            final_value = int("$value")
        except:
            final_value = float("$value")
    elif "$type" == "boolean":
        final_value = "$value".lower() in ("true", "yes", "1")
    
    # 设置最终值
    last_key = keys[-1]
    if last_key:
        current[last_key] = final_value
    
    # 写回文件
    with open("$file", 'w') as f:
        toml.dump(data, f)
    
    sys.exit(0)
except Exception as e:
    print(f"Error: {e}", file=sys.stderr)
    sys.exit(1)
EOF
    
    local result=$?
    if [[ $result -ne 0 ]] && [[ -f "${file}.bak" ]]; then
        mv "${file}.bak" "$file"
    else
        rm -f "${file}.bak"
    fi
    
    return $result
}

# 函数: Python删除TOML键
_toml_delete_python() {
    local file="$1"
    local path="$2"
    
    [[ -f "$file" ]] && cp "$file" "${file}.bak"
    
    python3 << EOF
import toml
import sys
import os

try:
    with open("$file", 'r') as f:
        data = toml.load(f)
    
    keys = "$path".strip('.').split('.')
    
    # 导航到父级
    current = data
    for key in keys[:-1]:
        if key and key in current:
            current = current[key]
        else:
            sys.exit(0)  # 路径不存在，无需删除
    
    # 删除最后一个键
    last_key = keys[-1]
    if last_key and last_key in current:
        del current[last_key]
    
    with open("$file", 'w') as f:
        toml.dump(data, f)
    
    sys.exit(0)
except Exception as e:
    print(f"Error: {e}", file=sys.stderr)
    sys.exit(1)
EOF
    
    local result=$?
    if [[ $result -ne 0 ]] && [[ -f "${file}.bak" ]]; then
        mv "${file}.bak" "$file"
    else
        rm -f "${file}.bak"
    fi
    
    return $result
}

###############################################################################
# 核心功能 - Shell实现（简化版）
###############################################################################

# 函数: Shell读取TOML值（简化实现）
_toml_read_shell() {
    local file="$1"
    local path="$2"
    local default="${3:-}"
    
    # 简化实现：仅支持简单的key=value格式
    local key="${path##*.}"
    local value=$(grep -E "^${key}\s*=" "$file" 2>/dev/null | head -n1 | sed -E 's/^[^=]+=\s*//' | sed 's/^["'"'"']\(.*\)["'"'"']$/\1/')
    
    echo "${value:-$default}"
}

# 函数: Shell写入TOML值（简化实现）
_toml_write_shell() {
    local file="$1"
    local path="$2"
    local value="$3"
    local type="${4:-string}"
    
    local key="${path##*.}"
    
    # 创建备份
    [[ -f "$file" ]] && cp "$file" "${file}.bak"
    
    # 格式化值
    local formatted_value="$value"
    if [[ "$type" == "string" ]]; then
        formatted_value="\"$value\""
    fi
    
    # 如果键存在，更新；否则追加
    if grep -q "^${key}\s*=" "$file" 2>/dev/null; then
        sed -i.tmp "s|^${key}\s*=.*|${key} = ${formatted_value}|" "$file"
        rm -f "${file}.tmp"
    else
        echo "${key} = ${formatted_value}" >> "$file"
    fi
    
    rm -f "${file}.bak"
}

###############################################################################
# 公共API
###############################################################################

# 函数: 验证TOML文件
toml_validate() {
    local file="$1"
    
    if [[ ! -f "$file" ]]; then
        log_error "toml" "文件不存在: $file"
        return 1
    fi
    
    case "$TOML_METHOD" in
        python)
            python3 -c "import toml; toml.load('$file')" 2>/dev/null
            ;;
        shell)
            # 简单验证：检查基本格式
            if grep -qE '^[a-zA-Z0-9_-]+\s*=' "$file"; then
                return 0
            else
                return 1
            fi
            ;;
        *)
            return 1
            ;;
    esac
}

# 函数: 读取TOML值
toml_read() {
    local file="$1"
    local path="$2"
    local default="${3:-}"
    
    if [[ ! -f "$file" ]]; then
        echo "$default"
        return 1
    fi
    
    case "$TOML_METHOD" in
        python)
            _toml_read_python "$file" "$path" "$default"
            ;;
        shell)
            _toml_read_shell "$file" "$path" "$default"
            ;;
        *)
            echo "$default"
            return 1
            ;;
    esac
}

# 函数: 写入TOML值
toml_write() {
    local file="$1"
    local path="$2"
    local value="$3"
    local type="${4:-string}"
    
    # 确保文件存在
    touch "$file"
    
    case "$TOML_METHOD" in
        python)
            _toml_write_python "$file" "$path" "$value" "$type"
            ;;
        shell)
            _toml_write_shell "$file" "$path" "$value" "$type"
            ;;
        *)
            return 1
            ;;
    esac
}

# 函数: 删除TOML键
toml_delete() {
    local file="$1"
    local path="$2"
    
    if [[ ! -f "$file" ]]; then
        return 1
    fi
    
    case "$TOML_METHOD" in
        python)
            _toml_delete_python "$file" "$path"
            ;;
        shell)
            local key="${path##*.}"
            sed -i.bak "/^${key}\s*=/d" "$file"
            rm -f "${file}.bak"
            ;;
        *)
            return 1
            ;;
    esac
}

# 函数: 列出TOML键（仅Shell实现）
toml_list_keys() {
    local file="$1"
    
    if [[ ! -f "$file" ]]; then
        return 1
    fi
    
    # 简单实现：提取所有键
    grep -E '^[a-zA-Z0-9_-]+\s*=' "$file" | sed 's/\s*=.*//' | sort -u
}

# 函数: 格式化TOML文件
toml_format() {
    local file="$1"
    
    if [[ ! -f "$file" ]]; then
        return 1
    fi
    
    case "$TOML_METHOD" in
        python)
            python3 << EOF
import toml

with open("$file", 'r') as f:
    data = toml.load(f)

with open("$file", 'w') as f:
    toml.dump(data, f)
EOF
            ;;
        *)
            # Shell实现：简单清理空行
            sed -i.bak '/^$/d' "$file"
            rm -f "${file}.bak"
            ;;
    esac
}

# 函数: 合并TOML文件
toml_merge() {
    local target="$1"
    local source="$2"
    local mode="${3:-merge}"
    
    if [[ ! -f "$source" ]]; then
        log_error "toml" "源文件不存在: $source"
        return 1
    fi
    
    if [[ "$TOML_METHOD" == "python" ]]; then
        cp "$target" "${target}.bak"
        
        python3 << EOF
import toml

target_data = {}
if __import__('os').path.exists("$target"):
    with open("$target", 'r') as f:
        target_data = toml.load(f)

with open("$source", 'r') as f:
    source_data = toml.load(f)

def merge_dict(d1, d2, mode):
    for k, v in d2.items():
        if k in d1 and isinstance(d1[k], dict) and isinstance(v, dict):
            merge_dict(d1[k], v, mode)
        else:
            if mode == "overwrite" or k not in d1:
                d1[k] = v

merge_dict(target_data, source_data, "$mode")

with open("$target", 'w') as f:
    toml.dump(target_data, f)
EOF
        
        if [[ $? -eq 0 ]]; then
            rm -f "${target}.bak"
        else
            mv "${target}.bak" "$target"
            return 1
        fi
    else
        log_warn "toml" "Shell实现不支持合并，请安装Python + toml模块"
        return 1
    fi
}

# 函数: 计算TOML文件哈希
toml_get_hash() {
    local file="$1"
    shift
    local keys=("$@")
    
    if [[ ! -f "$file" ]]; then
        return 1
    fi
    
    local hash_input=""
    
    if [[ ${#keys[@]} -eq 0 ]]; then
        # 整个文件
        hash_input=$(cat "$file")
    else
        # 指定键
        for key in "${keys[@]}"; do
            local value=$(toml_read "$file" "$key")
            hash_input+="${key}=${value}"$'\n'
        done
    fi
    
    # 计算哈希
    if command -v md5sum &>/dev/null; then
        echo "$hash_input" | md5sum | awk '{print $1}'
    elif command -v cksum &>/dev/null; then
        echo "$hash_input" | cksum | awk '{print $1}'
    else
        echo "$hash_input" | wc -c
    fi
}

# 函数: 保存哈希
toml_save_hash() {
    local file="$1"
    local hash_file="${2:-${file}.hash}"
    
    local hash=$(toml_get_hash "$file")
    echo "$hash" > "$hash_file"
}

# 函数: 检查变更
toml_check_changed() {
    local file="$1"
    local hash_file="${2:-${file}.hash}"
    
    if [[ ! -f "$hash_file" ]]; then
        return 0  # 没有保存的哈希，视为已变更
    fi
    
    local old_hash=$(cat "$hash_file")
    local new_hash=$(toml_get_hash "$file")
    
    [[ "$old_hash" != "$new_hash" ]]
}

# 函数: 帮助信息
toml_help() {
    cat << 'EOF'
TOML配置文件操作模块

支持的方法:
  - Python + toml模块（推荐，功能完整）
  - 纯Shell实现（功能受限）

函数列表:
  toml_validate <file>                     验证TOML文件格式
  toml_read <file> <path> [default]        读取TOML值
  toml_write <file> <path> <value> [type]  写入TOML值
  toml_delete <file> <path>                删除TOML键
  toml_list_keys <file>                    列出所有键
  toml_format <file>                       格式化TOML文件
  toml_merge <target> <source> [mode]      合并TOML文件
  toml_get_hash <file> [keys...]           计算文件哈希
  toml_save_hash <file> [hash_file]        保存哈希值
  toml_check_changed <file> [hash_file]    检查文件变更

路径格式: .section.subsection.key

示例:
  toml_read "config.toml" ".database.host" "localhost"
  toml_write "config.toml" ".app.port" "8080" "number"
  toml_delete "config.toml" ".app.debug"

依赖安装:
  # Python + toml
  pip3 install toml

当前方法: $TOML_METHOD
EOF
}

# 初始化
_toml_init

# 日志函数（如果未定义）
if ! declare -f log_error &>/dev/null; then
    log_error() { echo "[ERROR] [$1] $2" >&2; }
    log_warn() { echo "[WARN] [$1] $2" >&2; }
    log_info() { echo "[INFO] [$1] $2" >&2; }
fi

